package com.rao.core.startcollect;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Exchanger;

@Component
@Slf4j
public class StartPrintUrlTagCollectEventBean implements ApplicationListener<ServletWebServerInitializedEvent> {

    /**
     * url交换器
     */
    public static Exchanger<List<String>> urlExchanger = new Exchanger<>();


    @Override
    public void onApplicationEvent(ServletWebServerInitializedEvent event) {

        List<String> urls = new LinkedList<>();
        ConfigurableListableBeanFactory configurableListableBeanFactory = ConfigurableListableBeanFactoryUtil.configurableListableBeanFactory;
        for (String beanDefinitionName : configurableListableBeanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(beanDefinitionName);
            //包扫描的bean
            if (beanDefinition instanceof ScannedGenericBeanDefinition) {
                ScannedGenericBeanDefinition scannedGenericBeanDefinition = (ScannedGenericBeanDefinition) beanDefinition;
                Set<MethodMetadata> methods = scannedGenericBeanDefinition.getMetadata().getAnnotatedMethods(StartPrintUrlTag.class.getName());
                if (methods.size() == 0) {
                    continue;
                }
                AnnotationMetadata metadata = ((ScannedGenericBeanDefinition) beanDefinition).getMetadata();
                Map<String, Object> classAnno = metadata.getAnnotationAttributes(RequestMapping.class.getName());
                String classUrl = null;
                Object path = classAnno.get("path");
                if (path != null) {
                    String[] us = (String[]) path;
                    if (us.length >= 1) {
                        classUrl = us[0];
                    }
                }
                for (MethodMetadata methodMetadata : methods) {
                    try {
                        MultiValueMap<String, Object> attributes = methodMetadata.getAllAnnotationAttributes(RequestMapping.class.getName());
                        List<Object> pathObj = attributes.get("path");
                        if (pathObj != null && pathObj.size() >= 1) {
                            String[] os = (String[]) pathObj.get(0);
                            String methodUrl = os[0];
                            String collectUrl = classUrl + methodUrl;
                            urls.add(collectUrl);
                            log.info("要permitAll的方法为-{}.{}", scannedGenericBeanDefinition.getBeanClassName(), methodMetadata.getMethodName());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        try {
            urlExchanger.exchange(urls);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
